//
// Created by Administrator on 2023/11/17.
//
#include "iostream"

using namespace std;
const int N = 1e5 + 10;

//n是元素个数 m是前m个有序
//size 是现在堆中的元素个数
int n, m, a[N], size_;

//下沉操作，将结点u进行下沉，小根堆下沉操作
void down(int u) {
    int min = u;//min表示此节点和其左右子节点中最小的那个

    if (u * 2 <= size_ && a[u * 2] < a[min])//左结点
        min = u * 2;
    if (u * 2 + 1 <= size_ && a[u * 2 + 1] < a[min])//右结点
        min = u * 2 + 1;

    //需要和左右结点替换
    if(min!=u){
        swap(a[min],a[u]);//和左右节点中最小的那个替换
        down(min);//继续，每次需要下沉到不能下沉
    }
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    size_ = n;

    //最后一个分支节点下标为 n/2下取整，将每个分支节点都进行下沉
    for (int i = n / 2; i > 0; i--) {
        down(i);
    }

    while (m--){
        cout<<a[1];//小根堆中的最小元素
        swap(a[1],a[size_]);//把最后一个元素提到第一个
        size_--;//已经找到一个元素的最终位置.
        down(1);
    }

    cout<<endl;
    //展示一下小根堆输出的是递减的
    for (int i =1; i <= n; ++i) {
        cout<<a[i]<<' ';
    }

}